package cx3k.dataaccess.test;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import cx3k.dataaccess.DataAccessService;
import cx3k.dataaccess.exceptions.DataAccessException;
import cx3k.scheduler.objects.Course;
import cx3k.scheduler.objects.Major;
import cx3k.scheduler.objects.Minor;
import cx3k.scheduler.objects.Profile;

public class DASDriver {

	private DataAccessService das;
	
	public DASDriver(DataAccessService das){
		this.das = das;
	}
	
	private void addMajors(Profile profile){
		System.out.println("Possible Majors:");
		List<Major> allMajors = new ArrayList<Major>(getDataAccess().getAllMajors().values());
		
		for(Major major : profile.getMajors()){
			if(allMajors.contains(major)){
				allMajors.remove(major);
			}
		}
		
		if(!allMajors.isEmpty()){
			int index = 1;
			for(Major major : allMajors){
				System.out.println(index++ + ".\t" + major.getProgram() + ": " + major.getDescription());
			}
			Set<Major> currentMajors = profile.getMajors();
			currentMajors.add(allMajors.remove(Util.getValidInt(1, index, "Select major") - 1));
			
			if(Util.getYesNo("Add double major?")){
				
				System.out.println("Possible Double Majors Majors:");
				index = 1;
				for(Major major : allMajors){
					System.out.println(index++ + ".\t" + major.getProgram() + ": " + major.getDescription());
				}
				
				currentMajors.add(allMajors.remove(Util.getValidInt(1, index, "Select major") - 1 ));
			} 
			
			profile.setMajors(currentMajors);
			
		} else {
			System.out.println("No majors in the system.  Skipping step...");
		}
	}
	
	private void addMinor(Profile profile){
	
		System.out.println("Possible Minors:");
		List<Minor> allMinors = new ArrayList<Minor>(getDataAccess().getAllMinors().values());
		
		for(Minor minor : profile.getMinors()){
			if(allMinors.contains(minor)){
				allMinors.remove(minor);
			}
		}
		
		if(!allMinors.isEmpty()){
			int index = 1;
			for(Minor minor : allMinors){
				System.out.println(index++ + ".\t" + minor.getProgram() + ": " + minor.getDescription());
			}
			Set<Minor> currentMinors = profile.getMinors();
			currentMinors.add(allMinors.remove(Util.getValidInt(1, index, "Select minor") - 1));
			
			profile.setMinors(currentMinors);
		} else {
			System.out.println("No minors in the system.  Skipping step...");
		}
	}
	
	public void createProfile(){
		Util.printHeader("Create Profile");
		
		Profile profile = new Profile();
		
		profile.setName(Util.getInput("Name"));
		
		addMajors(profile);
		
		if(Util.getYesNo("Add minor?")){
			addMinor(profile);
		}
		
		saveProfile(profile);
		
	}
	
	private DataAccessService getDataAccess(){
		return das;
	}
	
	public void listCourses(){
		
		Util.printHeader("List Courses");
		
		if(getDataAccess().getAllCourses().isEmpty()){
			System.out.println("***No Courses in Storage***");
		}
		
		for(Course course : getDataAccess().getAllCourses().values()){
			System.out.println("   - " + course.getDegreeProgram() + " " + course.getCourseNum() + ": " + course.getDescription());
		}
		
		Util.getYesNo("Continue?");
	}
	
	public void listProfiles(){
		
		Util.printHeader("List Profiles");
		
		try {
			List<Profile> allProfiles = new ArrayList<Profile>(getDataAccess().getProfiles().values());
		
			System.out.println("Select a profile from the list below, or enter " + (allProfiles.size() + 1) + " to return.");
			
			int index = 1;
			
			for(Profile profile : allProfiles){
				System.out.println(index++ + ".\t" + profile.getName() + " [" + profile.getProfileId() + "]");
			}
			
			System.out.println(index + ".\tReturn");
			
			int userInput = Util.getValidInt(1, index, "Selection");
			
			if(userInput != index){
				loadProfile(allProfiles.get(userInput - 1));
			}
		} catch (DataAccessException e) {
			System.err.println("Could not list all profiles: " + e.getMessage());
		}
	}
	
	public void loadProfile(){
		
		Util.printHeader("Load Profile");
		
		int pid = Util.getValidInt(1, "Enter ID of profile to load");
		Profile result = null;
		
		try {
			result = loadProfile(pid);
			
			if(result == null){
				System.out.println("Specified profile ID (" + pid + ") was not mapped to a valid Profile.");
			} else {
				loadProfile(result);
			}
		} catch (DataAccessException e) {
			System.err.println("Could not load the Profile specified (ID = " + pid +"): " + e.getMessage());
		}
	}
	
	private Profile loadProfile(int profileId) throws DataAccessException{
		return getDataAccess().getProfile(profileId);
	}
	
	private void loadProfile(Profile profile){
		
	
		if(profile != null){		
			
			printProfile(profile);
			
			if(Util.getYesNo("Delete profile?")){
				try {
					getDataAccess().deleteProfile(profile);
				} catch (DataAccessException e) {
					System.err.println("Could not delete profile: " + e.getMessage());
				}
			} else {
				if(Util.getYesNo("Make changes to profile?")){
					modifyProfile(profile);
				}
			}
			
			
		} 
	}
	
	private void modifyProfile(Profile profile){
		System.out.println("\nCurrent name: " + profile.getName());
		
		if(Util.getYesNo("Change name?")){
			profile.setName(Util.getInput("Name"));
		}
		
		System.out.println("\nCurrent majors: ");
		
		List<Major> deleteMajors = new ArrayList<Major>();
		
		if(profile.getMajors().isEmpty()){
			System.out.println("***No Major Selected***");
		} else {
		
			for(Major major : profile.getMajors()){
				System.out.println(major.getProgram() + ": " + major.getDescription());
				if(Util.getYesNo("Delete major?")){
					deleteMajors.add(major);
				}
			}
			
			if(!deleteMajors.isEmpty()){
				Set<Major> majors = profile.getMajors();
				
				for(Major major : deleteMajors){
					majors.remove(major);
				}
				
				profile.setMajors(majors);
			}
		}
		
		if(Util.getYesNo("Add major?")){
			addMajors(profile);
		}
		
		System.out.println("\nCurrent minors:");
		
		if(profile.getMinors().isEmpty()){
			System.out.println("***No Minors Selected***");
		} else {
			
			List<Minor> deleteMinors = new ArrayList<Minor>();
			
			for(Minor minor : profile.getMinors()){
				System.out.println(minor.getProgram() + ": " + minor.getDescription());
				if(Util.getYesNo("Delete minor?")){
					deleteMinors.add(minor);
				}
			}
			
			if(!deleteMinors.isEmpty()){
				Set<Minor> minors = profile.getMinors();
				
				for(Minor minor : deleteMinors){
					minors.remove(minor);
				}
				
				profile.setMinors(minors);
			}
		}
		
		if(Util.getYesNo("Add minor?")){
			addMinor(profile);
		}
		
		saveProfile(profile);
	}
	
	private void printProfile(Profile profile){
		System.out.println("\n");
		System.out.println("+------------------------------------------------+");
		System.out.println("| PROFILE                                        |");
		System.out.printf("| Name: %-40s |\n", profile.getName());
		System.out.println("|                                                |");
		System.out.println("| Majors:                                        |");
		
		if(profile.getMajors().isEmpty()){
			System.out.println("|   No majors selected.                          |");
		}
		
		for(Major major : profile.getMajors()){
			System.out.printf("|   - %-42s |\n", major.getProgram() + ": " + major.getDescription());
		}
		
		System.out.println("|                                                |");
		System.out.println("| Minors:                                        |");
		
		if(profile.getMinors().isEmpty()){
			System.out.println("|   No minors selected.                          |");
		}
		
		for(Minor minor : profile.getMinors()){
			System.out.print("|   - "); //6
			System.out.printf("%-42s", minor.getProgram() + ": " + minor.getDescription());
			System.out.println(" |"); //2
		}
		
		System.out.println("+------------------------------------------------+");
	}
	
	private void saveProfile(Profile profile){
		if(Util.getYesNo("Commit changes to the database?")){
			
			try{
				getDataAccess().saveProfile(profile);
				
				System.out.println("Profile saved successfully (id #" + profile.getProfileId() + ").");
			
			} catch (DataAccessException e) {
				System.err.println("Could not save profile: " + e.getMessage());
			}
		} else {
			System.out.println("Changes not saved.");
		}
	}
}
